(function(global){    
    /**
     * JavaScript原生Function对象扩展。 
     * @class Function
     * @module JavaScript core extension 
     */   
     
    var _slice = Array.prototype.slice;
     
    ujs.define('fun', 'ujs', {
        /**
         * 空函数
         */
        empty : function(){},
        /**
         * 管子函数.
         */
        pipe : function(){
            var args = arguments, argsLen = args.length;  
            if(argsLen){
                return argsLen === 1 ? args[0] : _slice.call(args, 0);
            }
        },
        /**
         * 将指定的参数转换为函数.
         */
        from : function(obj){
            return typeof obj == 'function' ? obj : function(){
                return obj;
            };
        },              
        /**
         * 获取函数名.
         */
        getName : function(fun) {
            var m = fun.toString().match(/^function\s(\w+)/);
            return m ? m[1] : "anonymous";
        },
        /**
         * 获取函数的形参列表.
         */
        getArguments : function(fun) {
            var m = fun.toString().match(/\((.*)\)/)[1];
            m = m.replace(/\s*/g,'');
            return m ? m.split(',') : [];
        },
        /**
         * 获取函数本身代码内容.
         */
        getBody : function(fun) {
            var m = fun.toString().match(/\{([\s\S]*)\}/m)[1];
            return m.replace(/^\s*\/\/.*$/mg,'');
        },
        //---------------------------------------------------------------------------------------------
        /**
         * 继承.
         * //TODO 重写.
         * @method extend
         * @param {Function} superFun 父类.
         * @return {Function} 子类.
         */    
        extend : function(baseFun, superFun, funName) {
            if (!superFun) {
                return baseFun;
            }    
            //子类    
            var subFun = eval([
                '(function {0}(){'.format( funName || baseFun.name || '' ),
                    'superFun.apply(this, arguments);',            
                    'baseFun.apply(this, arguments);',  
                '})'
            ].join(''));            
            Object.extend(true, subFun.prototype, superFun.prototype);    //superFun.prototype 内可能有数据成员, 使用深拷贝。

            subFun.prototype.constructor = subFun;
            subFun.superFunction = subFun.prototype.superFunction = superFun;
            return subFun;
        },
        /**
         * 检测指定的对象是否是当前构造函数的实例。
         * TODO 测试
         * @method detectInstance
         * @param {Object} obj
         * @return {Boolean}
         */
        detectInstance : function(fun, obj){
            var constructorFun = obj.constructor;
            do{
                if(constructorFun === fun){
                    return true;
                } else {
                    constructorFun = constructorFun.superFunction;
                }            
            } while(constructorFun);
            return false;
        },
        //---------------------------------------------------------------------------------------------
        /**
         * TODO: 测试一下.
         * Returns a function, that, as long as it continues to be invoked, will not be triggered. 
         * The function will be called after it stops being called for N milliseconds. 
         * If `immediate` is passed, trigger the function on the leading edge, instead of the trailing.
         */
        debounce : function(fun, wait, immediate) {
            var _taskPtr;
            return function() {
                var ctx = this, args = arguments;
                var callNow = immediate && !_taskPtr;
                clearTimeout(_taskPtr);
                _taskPtr = setTimeout(function() {
                    _taskPtr = null;
                    if (!immediate) fun.apply(ctx, args);
                }, wait);
                if (callNow) fun.apply(ctx, args);
            };
        },  
        /**
         * Defer execution of a function.
         * 
         * This method will defer execution of the function ms milliseconds. 
         * If an object obj is provided then the function will be executed as a method on the object.
         * 
         * Any extra arguments a2...an will be passed along to the function.
         * 
         * @param ms {Number}
         * @param ctx {Object}
         */
        defer : function(fun, ms, ctx/*, [ Mixed a2...an ]*/) {
            var a = _slice.call(arguments, 3);
            return window.setTimeout(function(){
                return fun.apply(ctx, a);
            }, ms || 0);
        },
        
        /**
         * Memoize (cache) results of a function call
         */
        memoize : function(fun /*Mixed a0 ... an*/) {
            if (!fun.results){
                fun.results = {};
            }            
            var args = _slice.call(arguments, 1);            
            if (fun.results[args]){
                return fun.results[args];
            } else {             
                fun.results[args] = fun.apply(null, args);
                return fun.results[args];
            }
        },
        /**
         * 使函数在指定作用域下执行.
         */
        bind : function(fun, ctx){
            var args = _slice.call(arguments, 1);        
            return function(){        
                return fun.apply(ctx, args);
            };
        },
        //---------------------------------------------------------------------------------------------
        /**
         * 重写Setter. 
         * 使参数如setter(key, value)的方法支持setter({key1:value1, key2:value2})式的复数调用.
         * @param {Boolean} isUsePlural 是否仅支持复数调用.
         * @return {Function} 
         */
        overloadSetter : function(fun, isUsePlural){
            return function(key, value){
                if(!String(key)) return this;
                if(isUsePlural || typeof key != 'string'){
                    var obj = key;
                    for (var prop in obj){
                        fun.call(this, prop, obj[prop]);
                    }     
                } else { 
                    fun.call(this, key, value);
                }      
                return this;
            };
        },
        /**
         * 重写Getter. 
         * 使参数如getter(key)的方法支持getter(key1, key2, ...)|getter([key1, key2, ...])式的复数调用.
         * @param {Boolean} isUsePlural 是否仅支持复数调用.
         * @return {Function}
         */
        overloadGetter : function(fun, isUsePlural){
            return function(key){
                var args, result;       
                if (typeof key != 'string'){
                    args = key;
                } else if (arguments.length > 1){
                    args = arguments;
                } else if (isUsePlural){
                    args = [ key ];
                }       
                if (args){
                    result = {};
                    for (var i=0; i<args.length; i++){
                        result[args[i]] = fun.call(this, args[i]);
                    }
                } else {
                    result = fun.call(this, key);
                }
                return result;
            };
        },
        //---------------------------------------------------------------------------------------------
        /**
         * 为构造函数添加实例成员.
         */
        implement : function(fun, key, value){
            var members;
            if(arguments.length === 3){
                members = {};
                members[key] = value;
            } else {
                members = key;
            }
            if(members){
                for(var prop in members){
                    if(members.hasOwnProperty(prop)){
                        fun.prototype[prop] = members[prop];
                    }
                }
            }
            return fun;
        },
        /**
         * 为构造函数添加静态成员.
         */
        static : function(fun, key, value){
            var members;
            if(arguments.length === 3){
                members = {};
                members[key] = value;
            } else {
                members = key;
            }
            if(members){
                for(var prop in members){
                    if(members.hasOwnProperty(prop)){
                        fun[prop] = members[prop];
                    }
                }
            }
            return fun;
        }
    });
})(window);